<!-- build time:Tue Feb 18 2020 17:19:27 GMT+0800 (China Standard Time) --><!DOCTYPE html><html lang="zh"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,minimal-ui"><meta name="renderer" content="webkit"><meta http-equiv="Cache-Control" content="no-transform"><meta http-equiv="Cache-Control" content="no-siteapp"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><meta name="format-detection" content="telephone=no,email=no,adress=no"><meta name="theme-color" content="#000000"><meta http-equiv="window-target" content="_top"><title>Spring Boot 数据库连接池入门 | calm&#39;s blog</title><meta name="description" content="摘要: 原创出处 http:&#x2F;&#x2F;www.iocoder.cn&#x2F;Spring-Boot&#x2F;datasource-pool&#x2F; 「芋道源码」，卡姆在此基础上略作修改，欢迎转载，保留摘要，谢谢！1. 概述在我们的项目中，数据库连接池基本是必不可少的组件。在目前数据库连接池的选型中，主要是Druid ，为监控而生的数据库连接池。HikariCP ，号称性能最好的数据库连接池。至于怎么选择，两者都非常优秀，不用"><meta property="og:type" content="article"><meta property="og:title" content="Spring Boot 数据库连接池入门"><meta property="og:url" content="https://calm_java.gitee.io/blog/2020/01/07/labs-springboot2-datasource-pool/index.html"><meta property="og:site_name" content="卡姆"><meta property="og:description" content="摘要: 原创出处 http:&#x2F;&#x2F;www.iocoder.cn&#x2F;Spring-Boot&#x2F;datasource-pool&#x2F; 「芋道源码」，卡姆在此基础上略作修改，欢迎转载，保留摘要，谢谢！1. 概述在我们的项目中，数据库连接池基本是必不可少的组件。在目前数据库连接池的选型中，主要是Druid ，为监控而生的数据库连接池。HikariCP ，号称性能最好的数据库连接池。至于怎么选择，两者都非常优秀，不用"><meta property="og:locale" content="zh_CN"><meta property="og:image" content="https://calm_java.gitee.io/blog/2020/01/07/labs-springboot2-datasource-pool/1.jpeg"><meta property="og:image" content="https://calm_java.gitee.io/blog/2020/01/07/labs-springboot2-datasource-pool/2.png"><meta property="article:published_time" content="2020-01-07T13:34:14.000Z"><meta property="article:modified_time" content="2020-01-07T14:27:18.275Z"><meta property="article:author" content="calm"><meta property="article:tag" content="数据库连接池"><meta name="twitter:card" content="summary"><meta name="twitter:image" content="https://calm_java.gitee.io/blog/2020/01/07/labs-springboot2-datasource-pool/1.jpeg"><link rel="canonical" href="https://calm_java.gitee.io/blog/2020/01/07/labs-springboot2-datasource-pool/index.html"><link rel="alternate" href="/atom.xml" title="卡姆" type="application/atom+xml"><link rel="icon" href="/blog/images/avatar.jpg" type="image/x-icon"><link rel="stylesheet" href="/blog/css/style.css"><link rel="stylesheet" href="//cdn.jsdelivr.net/npm/gitalk@1.4.0/dist/gitalk.min.css"><meta name="generator" content="Hexo 4.2.0"></head><body class="main-center theme-green" itemscope itemtype="http://schema.org/WebPage"><header class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="slimContent"><div class="navbar-header"><div class="profile-block text-center"><a id="avatar" href="https://github.com/yuyong725" target="_blank"><img class="img-circle img-rotate" src="/blog/images/avatar.jpg" width="200" height="200"></a><h2 id="name" class="hidden-xs hidden-sm">卡姆</h2><h3 id="title" class="hidden-xs hidden-sm hidden-md">a Java coder need calm</h3><small id="location" class="text-muted hidden-xs hidden-sm"><i class="icon icon-map-marker"></i> hangzhou, China</small></div><div class="search" id="search-form-wrap"><form class="search-form sidebar-form"><div class="input-group"><input type="text" class="search-form-input form-control" placeholder="搜索"> <span class="input-group-btn"><button type="submit" class="search-form-submit btn btn-flat" onclick="return!1"><i class="icon icon-search"></i></button></span></div></form><div class="ins-search"><div class="ins-search-mask"></div><div class="ins-search-container"><div class="ins-input-wrapper"><input type="text" class="ins-search-input" placeholder="想要查找什么..." x-webkit-speech> <button type="button" class="close ins-close ins-selectable" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button></div><div class="ins-section-wrapper"><div class="ins-section-container"></div></div></div></div></div><button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target="#main-navbar" aria-controls="main-navbar" aria-expanded="false"><span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span></button></div><nav id="main-navbar" class="collapse navbar-collapse" itemscope itemtype="http://schema.org/SiteNavigationElement" role="navigation"><ul class="nav navbar-nav main-nav"><li class="menu-item menu-item-home"><a href="/blog/."><i class="icon icon-home-fill"></i> <span class="menu-title">首页</span></a></li><li class="menu-item menu-item-archives"><a href="/blog/archives"><i class="icon icon-archives-fill"></i> <span class="menu-title">归档</span></a></li><li class="menu-item menu-item-categories"><a href="/blog/categories"><i class="icon icon-folder"></i> <span class="menu-title">分类</span></a></li><li class="menu-item menu-item-tags"><a href="/blog/tags"><i class="icon icon-tags"></i> <span class="menu-title">标签</span></a></li><li class="menu-item menu-item-repository"><a href="/blog/repository"><i class="icon icon-project"></i> <span class="menu-title">项目</span></a></li><li class="menu-item menu-item-books"><a href="/blog/books"><i class="icon icon-book-fill"></i> <span class="menu-title">书单</span></a></li><li class="menu-item menu-item-links"><a href="/blog/links"><i class="icon icon-friendship"></i> <span class="menu-title">友链</span></a></li><li class="menu-item menu-item-about"><a href="/blog/about"><i class="icon icon-cup-fill"></i> <span class="menu-title">关于</span></a></li></ul><ul class="social-links"><li><a href="https://github.com/yuyong725" target="_blank" title="Github" data-toggle="tooltip" data-placement="top"><i class="icon icon-github"></i></a></li></ul></nav></div></header><aside class="sidebar" itemscope itemtype="http://schema.org/WPSideBar"><div class="slimContent"><div class="widget"><h3 class="widget-title">公告</h3><div class="widget-body"><div id="board"><div class="content"><p>欢迎交流与分享经验!</p></div></div></div></div><div class="widget"><h3 class="widget-title">分类</h3><div class="widget-body"><ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/blog/categories/CI-DI/">CI/DI</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/blog/categories/git/">git</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/blog/categories/labs/">labs</a><span class="category-list-count">14</span></li></ul></div></div><div class="widget"><h3 class="widget-title">标签</h3><div class="widget-body"><ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/MyBatis/" rel="tag">MyBatis</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/Oauth2/" rel="tag">Oauth2</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/Spring-Security/" rel="tag">Spring Security</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/SpringMVC/" rel="tag">SpringMVC</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/docker/" rel="tag">docker</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/dubbo/" rel="tag">dubbo</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/git/" rel="tag">git</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/jdbctemplate/" rel="tag">jdbctemplate</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/jerkins/" rel="tag">jerkins</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/job/" rel="tag">job</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/jpa/" rel="tag">jpa</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/pdf/" rel="tag">pdf</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/redis/" rel="tag">redis</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/%E5%88%86%E5%BA%93%E5%88%86%E8%A1%A8/" rel="tag">分库分表</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/%E5%A4%9A%E6%95%B0%E6%8D%AE%E6%BA%90/" rel="tag">多数据源</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/%E6%95%B0%E6%8D%AE%E5%BA%93%E7%89%88%E6%9C%AC%E7%AE%A1%E7%90%86/" rel="tag">数据库版本管理</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5%E6%B1%A0/" rel="tag">数据库连接池</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/%E7%BC%93%E5%AD%98/" rel="tag">缓存</a><span class="tag-list-count">2</span></li></ul></div></div><div class="widget"><h3 class="widget-title">标签云</h3><div class="widget-body tagcloud"><a href="/blog/tags/MyBatis/" style="font-size:13px">MyBatis</a> <a href="/blog/tags/Oauth2/" style="font-size:13px">Oauth2</a> <a href="/blog/tags/Spring-Security/" style="font-size:13px">Spring Security</a> <a href="/blog/tags/SpringMVC/" style="font-size:13px">SpringMVC</a> <a href="/blog/tags/docker/" style="font-size:13px">docker</a> <a href="/blog/tags/dubbo/" style="font-size:13px">dubbo</a> <a href="/blog/tags/git/" style="font-size:13px">git</a> <a href="/blog/tags/jdbctemplate/" style="font-size:13px">jdbctemplate</a> <a href="/blog/tags/jerkins/" style="font-size:13px">jerkins</a> <a href="/blog/tags/job/" style="font-size:14px">job</a> <a href="/blog/tags/jpa/" style="font-size:13px">jpa</a> <a href="/blog/tags/pdf/" style="font-size:13px">pdf</a> <a href="/blog/tags/redis/" style="font-size:13px">redis</a> <a href="/blog/tags/%E5%88%86%E5%BA%93%E5%88%86%E8%A1%A8/" style="font-size:13px">分库分表</a> <a href="/blog/tags/%E5%A4%9A%E6%95%B0%E6%8D%AE%E6%BA%90/" style="font-size:13px">多数据源</a> <a href="/blog/tags/%E6%95%B0%E6%8D%AE%E5%BA%93%E7%89%88%E6%9C%AC%E7%AE%A1%E7%90%86/" style="font-size:13px">数据库版本管理</a> <a href="/blog/tags/%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5%E6%B1%A0/" style="font-size:13px">数据库连接池</a> <a href="/blog/tags/%E7%BC%93%E5%AD%98/" style="font-size:14px">缓存</a></div></div><div class="widget"><h3 class="widget-title">归档</h3><div class="widget-body"><ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/02/">二月 2020</a><span class="archive-list-count">5</span></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/01/">一月 2020</a><span class="archive-list-count">8</span></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2019/12/">十二月 2019</a><span class="archive-list-count">4</span></li></ul></div></div><div class="widget"><h3 class="widget-title">最新文章</h3><div class="widget-body"><ul class="recent-post-list list-unstyled no-thumbnail"><li><div class="item-inner"><p class="item-category"><a class="category-link" href="/blog/categories/labs/">labs</a></p><p class="item-title"><a href="/blog/2020/02/18/labs-springboot2-async-Job/" class="title">Spring Boot 异步任务入门</a></p><p class="item-date"><time datetime="2020-02-18T05:10:39.000Z" itemprop="datePublished">2020-02-18</time></p></div></li><li><div class="item-inner"><p class="item-category"><a class="category-link" href="/blog/categories/labs/">labs</a></p><p class="item-title"><a href="/blog/2020/02/18/labs-springboot2-job/" class="title">Spring Boot 定时任务入门</a></p><p class="item-date"><time datetime="2020-02-18T02:26:31.000Z" itemprop="datePublished">2020-02-18</time></p></div></li><li><div class="item-inner"><p class="item-category"><a class="category-link" href="/blog/categories/labs/">labs</a></p><p class="item-title"><a href="/blog/2020/02/17/labs-springboot2-database-version-control/" class="title">Spring Boot 数据库版本管理入门</a></p><p class="item-date"><time datetime="2020-02-17T12:05:54.000Z" itemprop="datePublished">2020-02-17</time></p></div></li><li><div class="item-inner"><p class="item-category"><a class="category-link" href="/blog/categories/labs/">labs</a></p><p class="item-title"><a href="/blog/2020/02/17/labs-springboot2-sharding-datasource/" class="title">Spring Boot 分库分表入门</a></p><p class="item-date"><time datetime="2020-02-17T08:15:31.000Z" itemprop="datePublished">2020-02-17</time></p></div></li><li><div class="item-inner"><p class="item-category"><a class="category-link" href="/blog/categories/labs/">labs</a></p><p class="item-title"><a href="/blog/2020/02/13/labs-springboot2-dynamic-datasource/" class="title">Spring Boot 多数据源（读写分离）入门</a></p><p class="item-date"><time datetime="2020-02-13T03:18:37.000Z" itemprop="datePublished">2020-02-13</time></p></div></li></ul></div></div></div></aside><aside class="sidebar sidebar-toc collapse in" id="collapseToc" itemscope itemtype="http://schema.org/WPSideBar"><div class="slimContent"><nav id="toc" class="article-toc"><h3 class="toc-title">文章目录</h3><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#1-概述"><span class="toc-text">1. 概述</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#2-HikariCP-单数据源"><span class="toc-text">2. HikariCP 单数据源</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#2-1-引入依赖"><span class="toc-text">2.1 引入依赖</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-2-应用配置文件"><span class="toc-text">2.2 应用配置文件</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-3-HikaricpSingleApplication"><span class="toc-text">2.3 HikaricpSingleApplication</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#3-HikariCP-多数据源"><span class="toc-text">3. HikariCP 多数据源</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#3-1-引入依赖"><span class="toc-text">3.1 引入依赖</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-2-应用配置文件"><span class="toc-text">3.2 应用配置文件</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-3-数据源配置类"><span class="toc-text">3.3 数据源配置类</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#3-3-1-错误的示例"><span class="toc-text">3.3.1 错误的示例</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-3-2-正确的示例"><span class="toc-text">3.3.2 正确的示例</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-4-HikaricpMultipleApplication"><span class="toc-text">3.4 HikaricpMultipleApplication</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#4-Druid-单数据源"><span class="toc-text">4. Druid 单数据源</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#4-1-引入依赖"><span class="toc-text">4.1 引入依赖</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-2-应用配置文件"><span class="toc-text">4.2 应用配置文件</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-3-DruidSingleApplication"><span class="toc-text">4.3 DruidSingleApplication</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-4-监控功能"><span class="toc-text">4.4 监控功能</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#5-Druid-多数据源"><span class="toc-text">5. Druid 多数据源</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#5-1-引入依赖"><span class="toc-text">5.1 引入依赖</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-2-应用配置"><span class="toc-text">5.2 应用配置</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-3-数据源配置类"><span class="toc-text">5.3 数据源配置类</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-4-Application"><span class="toc-text">5.4 Application</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-5-监控功能"><span class="toc-text">5.5 监控功能</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#666-彩蛋"><span class="toc-text">666. 彩蛋</span></a></li></ol></nav></div></aside><main class="main" role="main"><div class="content"><article id="post-labs-springboot2-datasource-pool" class="article article-type-post" itemscope itemtype="http://schema.org/BlogPosting"><div class="article-header"><h1 class="article-title" itemprop="name">Spring Boot 数据库连接池入门</h1><div class="article-meta"><span class="article-date"><i class="icon icon-calendar-check"></i> <a href="/blog/2020/01/07/labs-springboot2-datasource-pool/" class="article-date"><time datetime="2020-01-07T13:34:14.000Z" itemprop="datePublished">2020-01-07</time></a></span> <span class="article-category"><i class="icon icon-folder"></i> <a class="article-category-link" href="/blog/categories/labs/">labs</a></span> <span class="article-tag"><i class="icon icon-tags"></i> <a class="article-tag-link" href="/blog/tags/%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5%E6%B1%A0/" rel="tag">数据库连接池</a></span> <span class="article-read hidden-xs"><i class="icon icon-eye-fill" aria-hidden="true"></i> <span id="busuanzi_container_page_pv"><span id="busuanzi_value_page_pv">0</span></span></span> <span class="post-comment"><i class="icon icon-comment"></i> <a href="/blog/2020/01/07/labs-springboot2-datasource-pool/#comments" class="article-comment-link">评论</a></span> <span class="post-wordcount hidden-xs" itemprop="wordCount">字数统计: 6.3k(字)</span> <span class="post-readcount hidden-xs" itemprop="timeRequired">阅读时长: 27(分)</span></div></div><div class="article-entry marked-body" itemprop="articleBody"><blockquote><p>摘要: 原创出处 <a href="http://www.iocoder.cn/Spring-Boot/datasource-pool/" target="_blank" rel="noopener">http://www.iocoder.cn/Spring-Boot/datasource-pool/</a> 「芋道源码」，卡姆在此基础上略作修改，欢迎转载，保留摘要，谢谢！</p></blockquote><h1 id="1-概述"><a href="#1-概述" class="headerlink" title="1. 概述"></a>1. 概述</h1><p>在我们的项目中，数据库连接池基本是必不可少的组件。在目前数据库连接池的选型中，主要是</p><ul><li><a href="https://github.com/alibaba/druid" target="_blank" rel="noopener">Druid</a> ，为<strong>监控</strong>而生的数据库连接池。</li><li><a href="https://github.com/brettwooldridge/HikariCP" target="_blank" rel="noopener">HikariCP</a> ，号称<strong>性能</strong>最好的数据库连接池。</li></ul><p>至于怎么选择，两者都非常优秀，不用过多纠结。</p><ul><li>Spring Boot 2.X 版本，默认采用 HikariCP 。</li><li>阿里大规模采用 Druid 。</li></ul><p>当然，如下有一些资料，胖友可以阅读参考：</p><ul><li><a href="https://github.com/alibaba/druid/wiki/Druid连接池介绍" target="_blank" rel="noopener">《Druid 连接池介绍》</a></li><li><a href="https://blog.csdn.net/clementad/article/details/46928621" target="_blank" rel="noopener">《为什么 HikariCP 被号称为性能最好的 Java 数据库连接池，如何配置使用》</a></li><li><a href="https://github.com/brettwooldridge/HikariCP/issues/232" target="_blank" rel="noopener">《alibaba/druid pool analysis》</a> ，一个小小的“撕逼”。</li></ul><p>下面，我们来进行 HikariCP 和 Druid 的入门，会配置单数据源和多数据源情况下的连接池。</p><h1 id="2-HikariCP-单数据源"><a href="#2-HikariCP-单数据源" class="headerlink" title="2. HikariCP 单数据源"></a>2. HikariCP 单数据源</h1><blockquote><p>示例代码对应仓库：<a href="https://github.com/yuyong725/labs-springboot2/tree/master/labs-springboot2-data-access/labs-springboot2-datasource-pool/labs-springboot2-hikaricp-single" target="_blank" rel="noopener">labs-springboot2-hikaricp-single</a>。</p><p>卡姆：推荐入门后，可以看看 HikariCP 的文档：<a href="https://github.com/brettwooldridge/HikariCP/wiki" target="_blank" rel="noopener">https://github.com/brettwooldridge/HikariCP/wiki</a> 。</p></blockquote><h2 id="2-1-引入依赖"><a href="#2-1-引入依赖" class="headerlink" title="2.1 引入依赖"></a>2.1 引入依赖</h2><p>在 <code>pom.xml</code>文件中，引入相关依赖。</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">"http://maven.apache.org/POM/4.0.0"</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">parent</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>labs-springboot2-datasource-pool<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>cn.javadog<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">parent</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">modelVersion</span>&gt;</span>4.0.0<span class="tag">&lt;/<span class="name">modelVersion</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>labs-springboot2-hikaricp-single<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 实现对数据库连接池的自动化配置 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-jdbc<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 本示例，我们使用 MySQL --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- 方便等会写单元测试 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">project</span>&gt;</span></span><br></pre></td></tr></table></figure><ul><li>无需主动引入 HikariCP 的依赖。因为在 Spring Boot 2.X 中，<code>spring-boot-starter-jdbc</code> 默认引入 <code>com.zaxxer.HikariCP</code> 依赖。</li></ul><h2 id="2-2-应用配置文件"><a href="#2-2-应用配置文件" class="headerlink" title="2.2 应用配置文件"></a>2.2 应用配置文件</h2><p>在 <code>application.yaml</code> 中，添加 HikariCP 配置，如下：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="comment"># datasource 数据源配置内容，对应 DataSourceProperties 配置属性类</span></span><br><span class="line">  <span class="attr">datasource:</span></span><br><span class="line">    <span class="attr">url:</span> <span class="string">jdbc:mysql://127.0.0.1:3306/labs-springboot2?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8</span></span><br><span class="line">    <span class="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line">    <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">    <span class="attr">password:</span> <span class="string">root</span></span><br><span class="line">    <span class="comment"># HikariCP 自定义配置，对应 HikariConfig 配置属性类</span></span><br><span class="line">    <span class="attr">hikari:</span></span><br><span class="line">      <span class="attr">minimum-idle:</span> <span class="number">20</span> <span class="comment"># 池中维护的最小空闲连接数，默认为 10 个。</span></span><br><span class="line">      <span class="attr">maximum-pool-size:</span> <span class="number">20</span> <span class="comment"># 池中最大连接数，包括闲置和使用中的连接，默认为 10 个。</span></span><br></pre></td></tr></table></figure><ul><li>在 <code>spring.datasource</code> 配置项下，我们可以添加数据源的<strong>通用</strong>配置。</li><li>在 <code>spring.datasource.hikari</code> 配置项下，我们可以添加 HikariCP 连接池的<strong>自定义</strong>配置。然后 <a href="https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration.java#L72-L92" target="_blank" rel="noopener">DataSourceConfiguration.Hikari</a> 会自动化配置 HikariCP 连接池。</li><li>相关配置简单看看即可，关于数据库连接池的调优的文章很少，不好深入😂</li></ul><blockquote><p>FROM <a href="https://blog.csdn.net/qq_32953079/article/details/81502237" target="_blank" rel="noopener">《HikariCP 连接池及其在 Spring Boot 中的配置》</a></p></blockquote><table><thead><tr><th align="left">配置项</th><th align="left">描述</th><th align="left">构造器默认值</th><th align="left">默认配置validate之后的值</th><th align="left">validate重置</th></tr></thead><tbody><tr><td align="left">autoCommit</td><td align="left">自动提交从池中返回的连接</td><td align="left">true</td><td align="left">true</td><td align="left">-</td></tr><tr><td align="left">connectionTimeout</td><td align="left">等待来自池的连接的最大毫秒数</td><td align="left">SECONDS.toMillis(30) = 30000</td><td align="left">30000</td><td align="left">如果小于250毫秒，则被重置回30秒</td></tr><tr><td align="left">idleTimeout</td><td align="left">连接允许在池中闲置的最长时间</td><td align="left">MINUTES.toMillis(10) = 600000</td><td align="left">600000</td><td align="left">如果idleTimeout+1秒&gt;maxLifetime 且 maxLifetime&gt;0，则会被重置为0（代表永远不会退出）；如果idleTimeout!=0且小于10秒，则会被重置为10秒</td></tr><tr><td align="left">maxLifetime</td><td align="left">池中连接最长生命周期</td><td align="left">MINUTES.toMillis(30) = 1800000</td><td align="left">1800000</td><td align="left">如果不等于0且小于30秒则会被重置回30分钟</td></tr><tr><td align="left">connectionTestQuery</td><td align="left">如果您的驱动程序支持JDBC4，我们强烈建议您不要设置此属性</td><td align="left">null</td><td align="left">null</td><td align="left">-</td></tr><tr><td align="left">minimumIdle</td><td align="left">池中维护的最小空闲连接数</td><td align="left">-1</td><td align="left">10</td><td align="left">minIdle&lt;0或者minIdle&gt;maxPoolSize,则被重置为maxPoolSize</td></tr><tr><td align="left">maximumPoolSize</td><td align="left">池中最大连接数，包括闲置和使用中的连接</td><td align="left">-1</td><td align="left">10</td><td align="left">如果maxPoolSize小于1，则会被重置。当minIdle&lt;=0被重置为DEFAULT_POOL_SIZE则为10;如果minIdle&gt;0则重置为minIdle的值</td></tr><tr><td align="left">metricRegistry</td><td align="left">该属性允许您指定一个 Codahale / Dropwizard <code>MetricRegistry</code> 的实例，供池使用以记录各种指标</td><td align="left">null</td><td align="left">null</td><td align="left">-</td></tr><tr><td align="left">healthCheckRegistry</td><td align="left">该属性允许您指定池使用的Codahale / Dropwizard HealthCheckRegistry的实例来报告当前健康信息</td><td align="left">null</td><td align="left">null</td><td align="left">-</td></tr><tr><td align="left">poolName</td><td align="left">连接池的用户定义名称，主要出现在日志记录和JMX管理控制台中以识别池和池配置</td><td align="left">null</td><td align="left">HikariPool-1</td><td align="left">-</td></tr><tr><td align="left">initializationFailTimeout</td><td align="left">如果池无法成功初始化连接，则此属性控制池是否将 <code>fail fast</code></td><td align="left">1</td><td align="left">1</td><td align="left">-</td></tr><tr><td align="left">isolateInternalQueries</td><td align="left">是否在其自己的事务中隔离内部池查询，例如连接活动测试</td><td align="left">false</td><td align="left">false</td><td align="left">-</td></tr><tr><td align="left">allowPoolSuspension</td><td align="left">控制池是否可以通过JMX暂停和恢复</td><td align="left">false</td><td align="left">false</td><td align="left">-</td></tr><tr><td align="left">readOnly</td><td align="left">从池中获取的连接是否默认处于只读模式</td><td align="left">false</td><td align="left">false</td><td align="left">-</td></tr><tr><td align="left">registerMbeans</td><td align="left">是否注册JMX管理Bean（<code>MBeans</code>）</td><td align="left">false</td><td align="left">false</td><td align="left">-</td></tr><tr><td align="left">catalog</td><td align="left">为支持 <code>catalog</code> 概念的数据库设置默认 <code>catalog</code></td><td align="left">driver default</td><td align="left">null</td><td align="left">-</td></tr><tr><td align="left">connectionInitSql</td><td align="left">该属性设置一个SQL语句，在将每个新连接创建后，将其添加到池中之前执行该语句。</td><td align="left">null</td><td align="left">null</td><td align="left">-</td></tr><tr><td align="left">driverClassName</td><td align="left">HikariCP将尝试通过仅基于jdbcUrl的DriverManager解析驱动程序，但对于一些较旧的驱动程序，还必须指定driverClassName</td><td align="left">null</td><td align="left">null</td><td align="left">-</td></tr><tr><td align="left">transactionIsolation</td><td align="left">控制从池返回的连接的默认事务隔离级别</td><td align="left">null</td><td align="left">null</td><td align="left">-</td></tr><tr><td align="left">validationTimeout</td><td align="left">连接将被测试活动的最大时间量</td><td align="left">SECONDS.toMillis(5) = 5000</td><td align="left">5000</td><td align="left">如果小于250毫秒，则会被重置回5秒</td></tr><tr><td align="left">leakDetectionThreshold</td><td align="left">记录消息之前连接可能离开池的时间量，表示可能的连接泄漏</td><td align="left">0</td><td align="left">0</td><td align="left">如果大于0且不是单元测试，则进一步判断：(leakDetectionThreshold &lt; SECONDS.toMillis(2) or (leakDetectionThreshold &gt; maxLifetime &amp;&amp; maxLifetime &gt; 0)，会被重置为0 . 即如果要生效则必须&gt;0，而且不能小于2秒，而且当maxLifetime &gt; 0时不能大于maxLifetime</td></tr><tr><td align="left">dataSource</td><td align="left">这个属性允许你直接设置数据源的实例被池包装，而不是让HikariCP通过反射来构造它</td><td align="left">null</td><td align="left">null</td><td align="left">-</td></tr><tr><td align="left">schema</td><td align="left">该属性为支持模式概念的数据库设置默认模式</td><td align="left">driver default</td><td align="left">null</td><td align="left">-</td></tr><tr><td align="left">threadFactory</td><td align="left">此属性允许您设置将用于创建池使用的所有线程的java.util.concurrent.ThreadFactory的实例。</td><td align="left">null</td><td align="left">null</td><td align="left">-</td></tr><tr><td align="left">scheduledExecutor</td><td align="left">此属性允许您设置将用于各种内部计划任务的java.util.concurrent.ScheduledExecutorService实例</td><td align="left">null</td><td align="left">null</td><td align="left">-</td></tr></tbody></table><h2 id="2-3-HikaricpSingleApplication"><a href="#2-3-HikaricpSingleApplication" class="headerlink" title="2.3 HikaricpSingleApplication"></a>2.3 HikaricpSingleApplication</h2><p>创建 <code>HikaricpSingleApplication</code>类，配置 <code>@SpringBootApplication</code> 注解即可。代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Application.java</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">HikaricpSingleApplication</span> <span class="keyword">implements</span> <span class="title">CommandLineRunner</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Logger logger = LoggerFactory.getLogger(Application<span class="class">.<span class="keyword">class</span>)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> DataSource dataSource;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 启动 Spring Boot 应用</span></span><br><span class="line">        SpringApplication.run(Application<span class="class">.<span class="keyword">class</span>, <span class="title">args</span>)</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">(String... args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">try</span> (Connection conn = dataSource.getConnection()) &#123;</span><br><span class="line">            <span class="comment">// 这里，可以做点什么</span></span><br><span class="line">            logger.info(<span class="string">"[run][获得连接：&#123;&#125;]"</span>, conn);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException(e);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>通过实现 <a href="https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-command-line-runner" target="_blank" rel="noopener">CommandLineRunner</a> 接口，应用启动完成后，回调 <code>#run(String... args)</code> 方法，输出下 Connection 信息。执行日志如下：</p><figure class="highlight verilog"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">2020</span>-<span class="number">01</span>-<span class="number">07</span> <span class="number">21</span>:<span class="number">44</span>:<span class="number">52</span><span class="variable">.017</span>  INFO <span class="number">15109</span> --- [           main] com<span class="variable">.zaxxer</span><span class="variable">.hikari</span><span class="variable">.HikariDataSource</span>       : HikariPool-<span class="number">1</span> - Starting...</span><br><span class="line"><span class="number">2020</span>-<span class="number">01</span>-<span class="number">07</span> <span class="number">21</span>:<span class="number">44</span>:<span class="number">52</span><span class="variable">.216</span>  INFO <span class="number">15109</span> --- [           main] com<span class="variable">.zaxxer</span><span class="variable">.hikari</span><span class="variable">.HikariDataSource</span>       : HikariPool-<span class="number">1</span> - Start completed.</span><br><span class="line"><span class="number">2020</span>-<span class="number">01</span>-<span class="number">07</span> <span class="number">21</span>:<span class="number">44</span>:<span class="number">52</span><span class="variable">.219</span>  INFO <span class="number">15109</span> --- [           main] c<span class="variable">.j</span><span class="variable">.l</span><span class="variable">.s</span><span class="variable">.h</span><span class="variable">.s</span><span class="variable">.HikaricpSingleApplication</span>    : [run][获得连接：HikariProxyConnection@<span class="number">1089584667</span> wrapping com<span class="variable">.mysql</span><span class="variable">.cj</span><span class="variable">.jdbc</span><span class="variable">.ConnectionImpl</span>@<span class="number">7</span>a791b66]</span><br></pre></td></tr></table></figure><ul><li>可以看到，HikariDataSource 成功初始化。</li></ul><h1 id="3-HikariCP-多数据源"><a href="#3-HikariCP-多数据源" class="headerlink" title="3. HikariCP 多数据源"></a>3. HikariCP 多数据源</h1><blockquote><p>示例代码对应仓库：<a href="https://github.com/yuyong725/labs-springboot2/tree/master/labs-springboot2-data-access/labs-springboot2-datasource-pool/labs-springboot2-hikaricp-multiple" target="_blank" rel="noopener">labs-springboot2-hikaricp-multiple</a> 。</p></blockquote><p>在本小节，我们会使用配置<strong>两个</strong>数据源的 HikariCP 连接池。</p><h2 id="3-1-引入依赖"><a href="#3-1-引入依赖" class="headerlink" title="3.1 引入依赖"></a>3.1 引入依赖</h2><p>和 <a href="https://calm_java.gitee.io/blog/2020/01/07/labs-springboot2-datasource-pool/">「2.1 引入依赖」</a> 是一致。</p><h2 id="3-2-应用配置文件"><a href="#3-2-应用配置文件" class="headerlink" title="3.2 应用配置文件"></a>3.2 应用配置文件</h2><p>在 <code>application.yaml</code> 中，添加 HikariCP 配置，如下：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="comment"># datasource 数据源配置内容</span></span><br><span class="line">  <span class="attr">datasource:</span></span><br><span class="line">    <span class="comment"># 订单数据源配置</span></span><br><span class="line">    <span class="attr">orders:</span></span><br><span class="line">      <span class="attr">url:</span> <span class="string">jdbc:mysql://127.0.0.1:3306/labs-springboot2?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8</span></span><br><span class="line">      <span class="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line">      <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">      <span class="attr">password:</span> <span class="string">root</span></span><br><span class="line">      <span class="comment"># HikariCP 自定义配置，对应 HikariConfig 配置属性类</span></span><br><span class="line">      <span class="attr">hikari:</span></span><br><span class="line">        <span class="attr">minimum-idle:</span> <span class="number">20</span> <span class="comment"># 池中维护的最小空闲连接数，默认为 10 个。</span></span><br><span class="line">        <span class="attr">maximum-pool-size:</span> <span class="number">20</span> <span class="comment"># 池中最大连接数，包括闲置和使用中的连接，默认为 10 个。</span></span><br><span class="line">    <span class="comment"># 用户数据源配置</span></span><br><span class="line">    <span class="attr">users:</span></span><br><span class="line">      <span class="attr">url:</span> <span class="string">jdbc:mysql://127.0.0.1:3306/labs-springboot2-multiple?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8</span></span><br><span class="line">      <span class="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line">      <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">      <span class="attr">password:</span> <span class="string">root</span></span><br><span class="line">      <span class="comment"># HikariCP 自定义配置，对应 HikariConfig 配置属性类</span></span><br><span class="line">      <span class="attr">hikari:</span></span><br><span class="line">        <span class="attr">minimum-idle:</span> <span class="number">15</span> <span class="comment"># 池中维护的最小空闲连接数，默认为 10 个。</span></span><br><span class="line">        <span class="attr">maximum-pool-size:</span> <span class="number">15</span> <span class="comment"># 池中最大连接数，包括闲置和使用中的连接，默认为 10 个。</span></span><br></pre></td></tr></table></figure><ul><li>我们在 <code>spring.datasource</code> 配置项下，定义了 <code>orders</code> 和 <code>users</code> 两个数据源的配置。而每个数据源的配置，和我们在 <a href="https://calm_java.gitee.io/blog/2020/01/07/labs-springboot2-datasource-pool/">「2.2 应用配置文件」</a> 是一致的。</li></ul><h2 id="3-3-数据源配置类"><a href="#3-3-数据源配置类" class="headerlink" title="3.3 数据源配置类"></a>3.3 数据源配置类</h2><h3 id="3-3-1-错误的示例"><a href="#3-3-1-错误的示例" class="headerlink" title="3.3.1 错误的示例"></a>3.3.1 错误的示例</h3><p>在网上，我们会看到这样配置多个数据源的配置类。代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span>(name = <span class="string">"ordersDataSource"</span>)</span><br><span class="line"><span class="meta">@ConfigurationProperties</span>(prefix = <span class="string">"spring.datasource.orders"</span>)</span><br><span class="line"><span class="function"><span class="keyword">public</span> DataSource <span class="title">ordersDataSource</span><span class="params">()</span> </span>&#123;</span><br><span class="line">   <span class="keyword">return</span> DataSourceBuilder.create().build();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Bean</span>(name = <span class="string">"usersDataSource"</span>)</span><br><span class="line"><span class="meta">@ConfigurationProperties</span>(prefix = <span class="string">"spring.datasource.users"</span>)</span><br><span class="line"><span class="function"><span class="keyword">public</span> DataSource <span class="title">ordersDataSource</span><span class="params">()</span> </span>&#123;</span><br><span class="line">   <span class="keyword">return</span> DataSourceBuilder.create().build();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>实际上，这样做的话，在部分场景下，会存在问题，这是为什么呢？</li><li>我们先来理解这段程序的用途。以 <code>#ordersDataSource()</code>方法为例子：<ul><li><code>DataSourceBuilder.create().build()</code> 代码段，会创建一个 DataSource 数据源。</li><li>搭配上 <code>@Bean(name = &quot;ordersDataSource&quot;)</code> 注解，会创建一个名字为 <code>&quot;ordersDataSource&quot;</code> 的 DataSource Bean 。这里，我们使用 HikariCP ，所以返回的是 HikariDataSource Bean 。</li><li><code>@ConfigurationProperties(prefix = &quot;spring.datasource.orders&quot;)</code> 注解，会将 <code>&quot;spring.datasource.orders&quot;</code> 配置项，逐个属性赋值给 DataSource Bean 。</li></ul></li><li>看起来貌似没问题，但是如果每个数据源如果有 HikariCP 的 <code>hikari</code> 自定义配置项时，<strong>它的自定义配置项无法设置到 HikariDataSource Bean 中</strong>。因为，<code>spring.datasource.orders.hikari</code> 是 <code>spring.datasource.orders</code> 的<strong>第二层</strong>属性。而 <a href="https://github.com/openbouquet/HikariCP/blob/master/src/main/java/com/zaxxer/hikari/HikariDataSource.java" target="_blank" rel="noopener">HikariDataSource</a> 的<a href="https://github.com/openbouquet/HikariCP/blob/master/src/main/java/com/zaxxer/hikari/HikariConfig.java" target="_blank" rel="noopener">配置属性</a>在<strong>第一层</strong>，这就导致无法正确的设置。简单点说，就是这一步只会设置 DataSource 相关的属性，如用户名、密码，不会设置连接池的属性。</li></ul><p>虽然存在该问题，但是大多数项目，我们并不会自定义 HikariCP 的 <code>hikari</code> 配置项，所以这个问题就偷偷藏起来，<strong>“不存在”</strong>了。</p><h3 id="3-3-2-正确的示例"><a href="#3-3-2-正确的示例" class="headerlink" title="3.3.2 正确的示例"></a>3.3.2 正确的示例</h3><p>当然，作为入门的示例，艿艿还是希望提供正确的做法。</p><p>创建 <code>DataSourceConfig</code> 配置类。代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// DataSourceConfig.java</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DataSourceConfig</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 创建 orders 数据源的配置对象</span></span><br><span class="line"><span class="comment">     * 读取 spring.datasource.orders 配置到 DataSourceProperties 对象</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Primary</span></span><br><span class="line">    <span class="meta">@Bean</span>(name = <span class="string">"ordersDataSourceProperties"</span>)</span><br><span class="line">    <span class="meta">@ConfigurationProperties</span>(prefix = <span class="string">"spring.datasource.orders"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> DataSourceProperties <span class="title">ordersDataSourceProperties</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> DataSourceProperties();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 创建 orders 数据源</span></span><br><span class="line"><span class="comment">     * 读取 spring.datasource.orders 配置到 HikariDataSource 对象</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Bean</span>(name = <span class="string">"ordersDataSource"</span>)</span><br><span class="line">    <span class="meta">@ConfigurationProperties</span>(prefix = <span class="string">"spring.datasource.orders.hikari"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> DataSource <span class="title">ordersDataSource</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 获得 DataSourceProperties 对象</span></span><br><span class="line">        DataSourceProperties properties =  <span class="keyword">this</span>.ordersDataSourceProperties();</span><br><span class="line">        <span class="comment">// 创建 HikariDataSource 对象</span></span><br><span class="line">        <span class="keyword">return</span> createHikariDataSource(properties);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 创建 users 数据源的配置对象</span></span><br><span class="line"><span class="comment">     * 读取 spring.datasource.users 配置到 DataSourceProperties 对象</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Bean</span>(name = <span class="string">"usersDataSourceProperties"</span>)</span><br><span class="line">    <span class="meta">@ConfigurationProperties</span>(prefix = <span class="string">"spring.datasource.users"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> DataSourceProperties <span class="title">usersDataSourceProperties</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> DataSourceProperties();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 创建 users 数据源</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Bean</span>(name = <span class="string">"usersDataSource"</span>)</span><br><span class="line">    <span class="meta">@ConfigurationProperties</span>(prefix = <span class="string">"spring.datasource.users.hikari"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> DataSource <span class="title">usersDataSource</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 获得 DataSourceProperties 对象</span></span><br><span class="line">        DataSourceProperties properties =  <span class="keyword">this</span>.usersDataSourceProperties();</span><br><span class="line">        <span class="comment">// 创建 HikariDataSource 对象</span></span><br><span class="line">        <span class="keyword">return</span> createHikariDataSource(properties);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> HikariDataSource <span class="title">createHikariDataSource</span><span class="params">(DataSourceProperties properties)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 创建 HikariDataSource 对象</span></span><br><span class="line">        HikariDataSource dataSource = properties.initializeDataSourceBuilder().type(HikariDataSource<span class="class">.<span class="keyword">class</span>).<span class="title">build</span>()</span>;</span><br><span class="line">        <span class="comment">// 设置线程池名</span></span><br><span class="line">        <span class="keyword">if</span> (StringUtils.hasText(properties.getName())) &#123;</span><br><span class="line">            dataSource.setPoolName(properties.getName());</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> dataSource;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li><p>这块代码，我们是参考 Spring Boot <a href="https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration.java#L72-L92" target="_blank" rel="noopener"><code>DataSourceConfiguration.Hikari</code></a> 配置类来实现的。</p></li><li><p><code>#ordersDataSourceProperties()</code>方法，创建<code>orders</code>数据源的 DataSourceProperties 配置对象。</p><ul><li><a href="http://www.yihaomen.com/article/java/581.htm" target="_blank" rel="noopener">@Primary</a> 注解，保证项目中有一个<strong>主</strong>的 DataSourceProperties Bean 。</li><li><code>new DataSourceProperties()</code> 代码段，会创建一个 DataSourceProperties 数据源的配置对象。</li><li>搭配上 <code>@Bean(name = &quot;ordersDataSourceProperties&quot;)</code> 注解，会创建一个名字为 <code>&quot;ordersDataSourceProperties&quot;</code> 的 DataSourceProperties Bean 。</li><li><code>@ConfigurationProperties(prefix = &quot;spring.datasource.orders&quot;)</code> 注解，会将 <code>&quot;spring.datasource.orders&quot;</code> 配置项，逐个属性赋值给 DataSourceProperties Bean 。</li></ul></li><li><p><code>#ordersDataSource()</code>方法，创建<code>orders</code> 数据源。</p><ul><li><code>&lt;1.1&gt;</code> 处，调用 <code>#ordersDataSourceProperties()</code> 方法，获得 <code>orders</code> 数据源的 DataSourceProperties 。</li><li><code>&lt;1.2&gt;</code> 处，调用 <code>#createHikariDataSource(DataSourceProperties properties)</code> 方法，创建 HikariDataSource 对象。这样，<code>&quot;spring.datasource.orders&quot;</code> 配置项，逐个属性赋值给 HikariDataSource Bean 。</li><li>搭配上 <code>@Bean(name = &quot;ordersDataSource&quot;)</code> 注解，会创建一个名字为 <code>&quot;ordersDataSource&quot;</code> 的 HikariDataSource Bean 。</li><li><code>@ConfigurationProperties(prefix = &quot;spring.datasource.orders.hikari&quot;)</code> 注解，会将 HikariCP 的 <code>&quot;spring.datasource.orders.hikari&quot;</code> 自定义配置项，逐个属性赋值给 HikariDataSource Bean 。</li></ul></li><li><p><code>users</code> 数据源的配置，同上，就不重复解释了。</p></li><li><p>胖友们可能会很好奇，为什么调用<code>#ordersDataSourceProperties()</code>方法，拿到的是填充好属性的<code>DataSourceProperties</code>对象，而不是刚刚new出炉的对象。类比在service里面自己调用自己的方法，除非全局设置<code>@EnableAspectJAutoProxy</code>，也没有手动的去拿<code>AopContext.currentProxy()</code>，直观上会觉得，加载方法上的Spring相关的注解不会生效，实际并非如此，如果debug，你会发现，<code>this</code> 是CGLIB代理后的对象，所有的方法都会被代理并加入了Spring的逻辑，因此这里拿到的已经是填充好属性的对象。</p><p><img src="1.jpeg" alt="this.usersDataSourceProperties()"></p></li></ul><h2 id="3-4-HikaricpMultipleApplication"><a href="#3-4-HikaricpMultipleApplication" class="headerlink" title="3.4 HikaricpMultipleApplication"></a>3.4 HikaricpMultipleApplication</h2><p>创建 <code>HikaricpMultipleApplication</code> 类，配置 <code>@SpringBootApplication</code> 注解即可。代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Application.java</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">HikaricpMultipleApplication</span> <span class="keyword">implements</span> <span class="title">CommandLineRunner</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Logger logger = LoggerFactory.getLogger(Application<span class="class">.<span class="keyword">class</span>)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Resource</span>(name = <span class="string">"ordersDataSource"</span>)</span><br><span class="line">    <span class="keyword">private</span> DataSource ordersDataSource;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Resource</span>(name = <span class="string">"usersDataSource"</span>)</span><br><span class="line">    <span class="keyword">private</span> DataSource usersDataSource;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 启动 Spring Boot 应用</span></span><br><span class="line">        SpringApplication.run(Application<span class="class">.<span class="keyword">class</span>, <span class="title">args</span>)</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">(String... args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// orders 数据源</span></span><br><span class="line">        <span class="keyword">try</span> (Connection conn = ordersDataSource.getConnection()) &#123;</span><br><span class="line">            <span class="comment">// 这里，可以做点什么</span></span><br><span class="line">            logger.info(<span class="string">"[run][ordersDataSource 获得连接：&#123;&#125;]"</span>, conn);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException(e);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// users 数据源</span></span><br><span class="line">        <span class="keyword">try</span> (Connection conn = usersDataSource.getConnection()) &#123;</span><br><span class="line">            <span class="comment">// 这里，可以做点什么</span></span><br><span class="line">            logger.info(<span class="string">"[run][usersDataSource 获得连接：&#123;&#125;]"</span>, conn);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException(e);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>执行日志如下：</p><figure class="highlight verilog"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">2020</span>-<span class="number">01</span>-<span class="number">07</span> <span class="number">22</span>:<span class="number">07</span>:<span class="number">04</span><span class="variable">.242</span>  INFO <span class="number">15232</span> --- [           main] com<span class="variable">.zaxxer</span><span class="variable">.hikari</span><span class="variable">.HikariDataSource</span>       : HikariPool-<span class="number">1</span> - Starting...</span><br><span class="line"><span class="number">2020</span>-<span class="number">01</span>-<span class="number">07</span> <span class="number">22</span>:<span class="number">07</span>:<span class="number">04</span><span class="variable">.504</span>  INFO <span class="number">15232</span> --- [           main] com<span class="variable">.zaxxer</span><span class="variable">.hikari</span><span class="variable">.HikariDataSource</span>       : HikariPool-<span class="number">1</span> - Start completed.</span><br><span class="line"><span class="number">2020</span>-<span class="number">01</span>-<span class="number">07</span> <span class="number">22</span>:<span class="number">07</span>:<span class="number">04</span><span class="variable">.507</span>  INFO <span class="number">15232</span> --- [           main] c<span class="variable">.j</span><span class="variable">.l</span><span class="variable">.s</span><span class="variable">.h</span><span class="variable">.m</span><span class="variable">.HikaricpMultipleApplication</span>  : [run][ordersDataSource 获得连接：HikariProxyConnection@<span class="number">609879567</span> wrapping com<span class="variable">.mysql</span><span class="variable">.cj</span><span class="variable">.jdbc</span><span class="variable">.ConnectionImpl</span>@<span class="number">6</span>edaa77a]</span><br><span class="line"><span class="number">2020</span>-<span class="number">01</span>-<span class="number">07</span> <span class="number">22</span>:<span class="number">07</span>:<span class="number">04</span><span class="variable">.510</span>  INFO <span class="number">15232</span> --- [           main] com<span class="variable">.zaxxer</span><span class="variable">.hikari</span><span class="variable">.HikariDataSource</span>       : HikariPool-<span class="number">2</span> - Starting...</span><br><span class="line"><span class="number">2020</span>-<span class="number">01</span>-<span class="number">07</span> <span class="number">22</span>:<span class="number">07</span>:<span class="number">04</span><span class="variable">.519</span>  INFO <span class="number">15232</span> --- [           main] com<span class="variable">.zaxxer</span><span class="variable">.hikari</span><span class="variable">.HikariDataSource</span>       : HikariPool-<span class="number">2</span> - Start completed.</span><br><span class="line"><span class="number">2020</span>-<span class="number">01</span>-<span class="number">07</span> <span class="number">22</span>:<span class="number">07</span>:<span class="number">04</span><span class="variable">.519</span>  INFO <span class="number">15232</span> --- [           main] c<span class="variable">.j</span><span class="variable">.l</span><span class="variable">.s</span><span class="variable">.h</span><span class="variable">.m</span><span class="variable">.HikaricpMultipleApplication</span>  : [run][usersDataSource 获得连接：HikariProxyConnection@<span class="number">1676010932</span> wrapping com<span class="variable">.mysql</span><span class="variable">.cj</span><span class="variable">.jdbc</span><span class="variable">.ConnectionImpl</span>@<span class="number">13</span>a37e2a]</span><br></pre></td></tr></table></figure><ul><li>可以看到，两个 HikariDataSource 成功初始化。</li></ul><p>多数据源和 JPA、MyBatis、JdbcTemplate 的集成，可以看看 <a href="http://www.iocoder.cn/Spring-Boot/dynamic-datasource/?self" target="_blank" rel="noopener">《芋道 Spring Boot 多数据源（读写分离）入门》</a> 文章。</p><h1 id="4-Druid-单数据源"><a href="#4-Druid-单数据源" class="headerlink" title="4. Druid 单数据源"></a>4. Druid 单数据源</h1><blockquote><p>示例代码对应仓库：<a href="https://github.com/yuyong725/labs-springboot2/tree/master/labs-springboot2-data-access/labs-springboot2-datasource-pool/labs-springboot2-druid-single" target="_blank" rel="noopener">labs-springboot2-druid-single</a> 。</p><p>卡姆：推荐入门后，可以看看 Druid 的文档：<a href="https://github.com/alibaba/druid/wiki/" target="_blank" rel="noopener">https://github.com/alibaba/druid/wiki/</a> 。</p></blockquote><h2 id="4-1-引入依赖"><a href="#4-1-引入依赖" class="headerlink" title="4.1 引入依赖"></a>4.1 引入依赖</h2><p>在 <code>pom.xml</code>文件中，引入相关依赖。</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">project</span> <span class="attr">xmlns</span>=<span class="string">"http://maven.apache.org/POM/4.0.0"</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag">         <span class="attr">xsi:schemaLocation</span>=<span class="string">"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">parent</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>labs-springboot2-datasource-pool<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>cn.javadog<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0-SNAPSHOT<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">parent</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">modelVersion</span>&gt;</span>4.0.0<span class="tag">&lt;/<span class="name">modelVersion</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>labs-springboot2-druid-single<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 保证 Spring JDBC 的依赖健全 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-jdbc<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- 实现对 Druid 连接池的自动化配置 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>druid-spring-boot-starter<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- 本示例，我们使用 MySQL --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- 实现对 Spring MVC 的自动化配置，因为我们需要看看 Druid 的监控功能 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- 方便等会写单元测试 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">scope</span>&gt;</span>test<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">project</span>&gt;</span></span><br></pre></td></tr></table></figure><p>具体每个依赖的作用，胖友自己认真看下艿艿添加的所有注释噢。S</p><h2 id="4-2-应用配置文件"><a href="#4-2-应用配置文件" class="headerlink" title="4.2 应用配置文件"></a>4.2 应用配置文件</h2><p>在 <code>application.yaml</code> 中，添加 Druid 配置，如下：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="comment"># datasource 数据源配置内容，对应 DataSourceProperties 配置属性类</span></span><br><span class="line">  <span class="attr">datasource:</span></span><br><span class="line">    <span class="attr">url:</span> <span class="string">jdbc:mysql://127.0.0.1:3306/labs-springboot2?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8</span></span><br><span class="line">    <span class="attr">driver-class-name:</span> <span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line">    <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">    <span class="attr">password:</span> <span class="string">root</span></span><br><span class="line">    <span class="attr">type:</span> <span class="string">com.alibaba.druid.pool.DruidDataSource</span> <span class="comment"># 设置类型为 DruidDataSource</span></span><br><span class="line">    <span class="comment"># Druid 自定义配置，对应 DruidDataSource 中的 setting 方法的属性</span></span><br><span class="line">    <span class="attr">druid:</span></span><br><span class="line">      <span class="attr">min-idle:</span> <span class="number">0</span> <span class="comment"># 池中维护的最小空闲连接数，默认为 0 个。</span></span><br><span class="line">      <span class="attr">max-active:</span> <span class="number">20</span> <span class="comment"># 池中最大连接数，包括闲置和使用中的连接，默认为 8 个。</span></span><br><span class="line">      <span class="attr">filter:</span></span><br><span class="line">        <span class="attr">stat:</span> <span class="comment"># 配置 StatFilter ，对应文档 https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE_StatFilter</span></span><br><span class="line">          <span class="attr">log-slow-sql:</span> <span class="literal">true</span> <span class="comment"># 开启慢查询记录</span></span><br><span class="line">          <span class="attr">slow-sql-millis:</span> <span class="number">5000</span> <span class="comment"># 慢 SQL 的标准，单位：毫秒</span></span><br><span class="line">      <span class="attr">stat-view-servlet:</span> <span class="comment"># 配置 StatViewServlet ，对应文档 https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE_StatViewServlet%E9%85%8D%E7%BD%AE</span></span><br><span class="line">        <span class="attr">enabled:</span> <span class="literal">true</span> <span class="comment"># 是否开启 StatViewServlet</span></span><br><span class="line">        <span class="attr">login-username:</span> <span class="string">admin</span> <span class="comment"># 账号</span></span><br><span class="line">        <span class="attr">login-password:</span> <span class="number">123456</span> <span class="comment"># 密码</span></span><br></pre></td></tr></table></figure><ul><li><code>spring.datasource</code> 配置项，设置 Spring 数据源的通用配置。其中，<code>spring.datasource.type</code> 配置项，<strong>需要主动</strong>设置使用 DruidDataSource 。因为默认情况下，<code>spring-boot-starter-jdbc</code> 的 <a href="https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceBuilder.java#L49-L50" target="_blank" rel="noopener">DataSourceBuilder</a> 会按照 <a href="https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceBuilder.java#L49-L50" target="_blank" rel="noopener"><code>DATA_SOURCE_TYPE_NAMES</code></a> 的顺序，尝试推断数据源的类型。</li><li><code>spring.datasource.druid</code> 配置项，设置 Druid 连接池的自定义配置。然后<a href="https://github.com/alibaba/druid/blob/master/druid-spring-boot-starter/src/main/java/com/alibaba/druid/spring/boot/autoconfigure/DruidDataSourceAutoConfigure.java" target="_blank" rel="noopener">DruidDataSourceAutoConfigure</a>会自动化配置 Druid 连接池。<ul><li>在 <a href="https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter#配置属性" target="_blank" rel="noopener">《Druid —— 配置属性》</a> 和 <a href="https://github.com/alibaba/druid/wiki/DruidDataSource配置属性列表" target="_blank" rel="noopener">《DruidDataSource 配置属性列表》</a> 下，提供了各种 Druid 的配置项，胖友可以自己看看。</li><li><code>filter.stat</code> 配置项，我们配置了 Druid <a href="https://github.com/alibaba/druid/blob/master/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java" target="_blank" rel="noopener">StatFilter</a> ，用于统计监控信息。对应文档 <a href="https://github.com/alibaba/druid/wiki/配置_StatFilter" target="_blank" rel="noopener">《Druid —— 配置_StatFilter》</a> 。要注意，StatFilter 并不是我们说的 <a href="https://github.com/javaee/servlet-spec/blob/master/src/main/java/javax/servlet/Filter.java" target="_blank" rel="noopener">javax.servlet.Filter</a> ，而是 Druid 提供的 <a href="https://github.com/alibaba/druid/wiki/配置_Filter配置" target="_blank" rel="noopener">Filter</a> 拓展机制。</li><li><code>filter.stat-view-servlet</code> 配置项，我们配置了 Druid <a href="https://github.com/alibaba/druid/blob/master/src/main/java/com/alibaba/druid/support/http/StatViewServlet.java" target="_blank" rel="noopener">StatViewServlet</a> ，用于提供监控信息的<strong>展示的 html 页面</strong>和 <strong>JSON API</strong> 。对应文档 <a href="https://github.com/alibaba/druid/wiki/配置_StatViewServlet配置" target="_blank" rel="noopener">《Druid —— 配置_StatViewServlet 配置》</a> 。StatViewServlet 就是我们说的 <a href="https://github.com/javaee/servlet-spec/blob/master/src/main/java/javax/servlet/Servlet.java" target="_blank" rel="noopener">javax.servlet.Filter</a> 。</li></ul></li></ul><h2 id="4-3-DruidSingleApplication"><a href="#4-3-DruidSingleApplication" class="headerlink" title="4.3 DruidSingleApplication"></a>4.3 DruidSingleApplication</h2><p>创建 <code>DruidSingleApplication</code> 类，配置 <code>@SpringBootApplication</code> 注解即可。代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DruidSingleApplication</span> <span class="keyword">implements</span> <span class="title">CommandLineRunner</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Logger logger = LoggerFactory.getLogger(Application<span class="class">.<span class="keyword">class</span>)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> DataSource dataSource;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 启动 Spring Boot 应用</span></span><br><span class="line">        SpringApplication.run(Application<span class="class">.<span class="keyword">class</span>, <span class="title">args</span>)</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">(String... args)</span> </span>&#123;</span><br><span class="line">        logger.info(<span class="string">"[run][获得数据源：&#123;&#125;]"</span>, dataSource.getClass());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>执行日志如下：</p><figure class="highlight verilog"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">2020</span>-<span class="number">01</span>-<span class="number">07</span> <span class="number">22</span>:<span class="number">14</span>:<span class="number">52</span><span class="variable">.692</span>  INFO <span class="number">15257</span> --- [           main] c<span class="variable">.a</span><span class="variable">.d</span><span class="variable">.s</span><span class="variable">.b</span><span class="variable">.a</span><span class="variable">.DruidDataSourceAutoConfigure</span> : Init DruidDataSource</span><br><span class="line"><span class="number">2020</span>-<span class="number">01</span>-<span class="number">07</span> <span class="number">22</span>:<span class="number">14</span>:<span class="number">52</span><span class="variable">.816</span>  INFO <span class="number">15257</span> --- [           main] com<span class="variable">.alibaba</span><span class="variable">.druid</span><span class="variable">.pool</span><span class="variable">.DruidDataSource</span>   : &#123;dataSource-<span class="number">1</span>&#125; inited</span><br><span class="line"><span class="number">2020</span>-<span class="number">01</span>-<span class="number">07</span> <span class="number">22</span>:<span class="number">14</span>:<span class="number">53</span><span class="variable">.274</span>  INFO <span class="number">15257</span> --- [           main] c<span class="variable">.j</span><span class="variable">.l</span><span class="variable">.s</span><span class="variable">.d</span><span class="variable">.single</span><span class="variable">.DruidSingleApplication</span>  : [run][获得数据源：<span class="keyword">class</span> com<span class="variable">.alibaba</span><span class="variable">.druid</span><span class="variable">.spring</span><span class="variable">.boot</span><span class="variable">.autoconfigure</span><span class="variable">.DruidDataSourceWrapper</span>]</span><br></pre></td></tr></table></figure><ul><li>可以看到，DruidDataSource 成功初始化。</li></ul><h2 id="4-4-监控功能"><a href="#4-4-监控功能" class="headerlink" title="4.4 监控功能"></a>4.4 监控功能</h2><p>因为我们在 <a href="https://calm_java.gitee.io/blog/2020/01/07/labs-springboot2-datasource-pool/">「4.2 应用配置中」</a> 中，做了如下操作：</p><ul><li>通过 <code>spring.datasource.filter.stat</code> 配置了 StatFilter ，统计监控信息。</li><li>通过 <code>spring.datasource.filter.stat-view-servlet</code> 配置了 StatViewServlet ，提供监控信息的展示的 html 页面和 JSON API 。</li></ul><p>所以我们在启动项目后，访问 <code>http://127.0.0.1:8080/druid</code> 地址，可以看到监控 html 页面。如下图所示：<img src="2.png" alt="监控界面"></p><ul><li><p>在界面的顶部，提供了数据源、SQL 监控、SQL 防火墙等等功能。</p></li><li><p>每个界面上，可以通过 <a href="https://calm_java.gitee.io/blog/2020/01/07/labs-springboot2-datasource-pool/">View JSON API</a> 获得数据的来源。同时，我们可以在 <a href="https://calm_java.gitee.io/blog/2020/01/07/labs-springboot2-datasource-pool/">JSON API( <code>http://127.0.0.1:8080/druid/api.html</code> )</a> 菜单对应的界面中，看到 StatViewServlet 内置的监控信息的 JSON API 列表。</p></li><li><p>因为监控信息是存储在 JVM 内存中，在 JVM 进程重启时，信息将会丢失。如果我们希望持久化到 MySQL、Elasticsearch、HBase 等存储器中，可以通过 StatViewServlet 提供的 JSON API 接口，采集监控信息。另外，有个 <a href="https://github.com/bungder/druid-aggregated-monitor" target="_blank" rel="noopener">druid-aggregated-monitor</a> 开源项目，提供了 集中监控分布式服务中的 Druid 连接池的方案和思路。</p></li><li><p>如果 StatViewServlet 提供的 JSON API 接口，无法满足我们的诉求，我们可以通过自定义 API 接口，使用 <a href="https://github.com/alibaba/druid/blob/master/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java" target="_blank" rel="noopener">DruidStatManagerFacade</a> 获得监控信息。使用示例 <a href="https://github.com/YunaiV/SpringBoot-Labs/blob/master/lab-19/lab-19-datasource-pool-druid-single/src/main/java/cn/iocoder/springboot/lab19/datasourcepool/controller/DruidStatController.java" target="_blank" rel="noopener">DruidStatController</a> 代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// DruidStatController.java</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DruidStatController</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping</span>(<span class="string">"/monitor/druid/stat"</span>)</span><br><span class="line">    <span class="meta">@Deprecated</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Object <span class="title">druidStat</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="comment">// `DruidStatManagerFacade#getDataSourceStatDataList()` 方法，可以获取所有数据源的监控数据。</span></span><br><span class="line">        <span class="comment">// 除此之外，DruidStatManagerFacade 还提供了一些其他方法，你可以按需选择使用。</span></span><br><span class="line">        <span class="keyword">return</span> DruidStatManagerFacade.getInstance().getDataSourceStatDataList();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>当然，绝大多数情况下，我们并不需要做这方面的拓展。</li></ul></li></ul><h1 id="5-Druid-多数据源"><a href="#5-Druid-多数据源" class="headerlink" title="5. Druid 多数据源"></a>5. Druid 多数据源</h1><blockquote><p>示例代码对应仓库：<a href="https://github.com/yuyong725/labs-springboot2/tree/master/labs-springboot2-data-access/labs-springboot2-datasource-pool/labs-springboot2-druid-multiple" target="_blank" rel="noopener">labs-springboot2-druid-multiple</a> 。</p></blockquote><p>在本小节，我们会使用配置<strong>两个</strong>数据源的 Druid 连接池。</p><h2 id="5-1-引入依赖"><a href="#5-1-引入依赖" class="headerlink" title="5.1 引入依赖"></a>5.1 引入依赖</h2><p>和 <a href="https://calm_java.gitee.io/blog/2020/01/07/labs-springboot2-datasource-pool/">「4.1 引入依赖」</a> 是一致。</p><h2 id="5-2-应用配置"><a href="#5-2-应用配置" class="headerlink" title="5.2 应用配置"></a>5.2 应用配置</h2><p>在 <code>application.yaml</code>中，添加 Druid 配置，如下：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="comment"># datasource 数据源配置内容</span></span><br><span class="line">  <span class="attr">datasource:</span></span><br><span class="line">    <span class="comment"># 订单数据源配置</span></span><br><span class="line">    <span class="attr">orders:</span></span><br><span class="line">      <span class="attr">url:</span> <span class="string">jdbc:mysql://127.0.0.1:3306/labs-springboot2?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8</span></span><br><span class="line">      <span class="attr">driver-class-name:</span> <span class="string">com.mysql.jdbc.Driver</span></span><br><span class="line">      <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">      <span class="attr">password:</span> <span class="string">root</span></span><br><span class="line">      <span class="attr">type:</span> <span class="string">com.alibaba.druid.pool.DruidDataSource</span> <span class="comment"># 设置类型为 DruidDataSource</span></span><br><span class="line">      <span class="comment"># Druid 自定义配置，对应 DruidDataSource 中的 setting 方法的属性</span></span><br><span class="line">      <span class="attr">min-idle:</span> <span class="number">0</span> <span class="comment"># 池中维护的最小空闲连接数，默认为 0 个。</span></span><br><span class="line">      <span class="attr">max-active:</span> <span class="number">20</span> <span class="comment"># 池中最大连接数，包括闲置和使用中的连接，默认为 8 个。</span></span><br><span class="line">    <span class="comment"># 用户数据源配置</span></span><br><span class="line">    <span class="attr">users:</span></span><br><span class="line">      <span class="attr">url:</span> <span class="string">jdbc:mysql://127.0.0.1:3306/labs-springboot2-multiple?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8</span></span><br><span class="line">      <span class="attr">driver-class-name:</span> <span class="string">com.mysql.jdbc.Driver</span></span><br><span class="line">      <span class="attr">username:</span> <span class="string">root</span></span><br><span class="line">      <span class="attr">password:</span></span><br><span class="line">      <span class="attr">type:</span> <span class="string">com.alibaba.druid.pool.DruidDataSource</span> <span class="comment"># 设置类型为 DruidDataSource</span></span><br><span class="line">      <span class="comment"># Druid 自定义配置，对应 DruidDataSource 中的 setting 方法的属性</span></span><br><span class="line">      <span class="attr">min-idle:</span> <span class="number">0</span> <span class="comment"># 池中维护的最小空闲连接数，默认为 0 个。</span></span><br><span class="line">      <span class="attr">max-active:</span> <span class="number">20</span> <span class="comment"># 池中最大连接数，包括闲置和使用中的连接，默认为 8 个。</span></span><br><span class="line">    <span class="comment"># Druid 自定已配置</span></span><br><span class="line">    <span class="attr">druid:</span></span><br><span class="line">      <span class="comment"># 过滤器配置</span></span><br><span class="line">      <span class="attr">filter:</span></span><br><span class="line">        <span class="attr">stat:</span> <span class="comment"># 配置 StatFilter ，对应文档 https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE_StatFilter</span></span><br><span class="line">          <span class="attr">log-slow-sql:</span> <span class="literal">true</span> <span class="comment"># 开启慢查询记录</span></span><br><span class="line">          <span class="attr">slow-sql-millis:</span> <span class="number">5000</span> <span class="comment"># 慢 SQL 的标准，单位：毫秒</span></span><br><span class="line">      <span class="comment"># StatViewServlet 配置</span></span><br><span class="line">      <span class="attr">stat-view-servlet:</span> <span class="comment"># 配置 StatViewServlet ，对应文档 https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE_StatViewServlet%E9%85%8D%E7%BD%AE</span></span><br><span class="line">        <span class="attr">enabled:</span> <span class="literal">true</span> <span class="comment"># 是否开启 StatViewServlet</span></span><br><span class="line">        <span class="attr">login-username:</span> <span class="string">admin</span> <span class="comment"># 账号</span></span><br><span class="line">        <span class="attr">login-password:</span> <span class="number">123456</span> <span class="comment"># 密码</span></span><br></pre></td></tr></table></figure><ul><li>不同于我们在 <a href="https://calm_java.gitee.io/blog/2020/01/07/labs-springboot2-datasource-pool/">「3.2 应用配置文件」</a> 中，我们将 Druid 的自定义配置，和 <code>url</code>、<code>driver-class-name</code> 等数据源的通用配置放在同一级，这样后续我们只需要使用 <code>@ConfigurationProperties(prefix = &quot;spring.datasource.orders&quot;)</code> 的方式，就能完成 DruidDataSource 的配置属性设置。</li><li>在 <code>spring.datasource.druid</code> 配置项下，我们还是配置了 <code>filter.stat</code> 和 <code>stat-view-servlet</code> 配置项，用于 Druid 监控功能。</li></ul><h2 id="5-3-数据源配置类"><a href="#5-3-数据源配置类" class="headerlink" title="5.3 数据源配置类"></a>5.3 数据源配置类</h2><p>创建 <a href="https://github.com/YunaiV/SpringBoot-Labs/blob/master/lab-19/lab-19-datasource-pool-druid-multiple/src/main/java/cn/iocoder/springboot/lab19/datasourcepool/config/DataSourceConfig.java" target="_blank" rel="noopener">DataSourceConfig</a> 配置类。代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// DataSourceConfig.java</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DataSourceConfig</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 创建 orders 数据源</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Primary</span></span><br><span class="line">    <span class="meta">@Bean</span>(name = <span class="string">"ordersDataSource"</span>)</span><br><span class="line">    <span class="meta">@ConfigurationProperties</span>(prefix = <span class="string">"spring.datasource.orders"</span>) <span class="comment">// 读取 spring.datasource.orders 配置到 HikariDataSource 对象</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> DataSource <span class="title">ordersDataSource</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> DruidDataSourceBuilder.create().build();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 创建 users 数据源</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Bean</span>(name = <span class="string">"usersDataSource"</span>)</span><br><span class="line">    <span class="meta">@ConfigurationProperties</span>(prefix = <span class="string">"spring.datasource.users"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> DataSource <span class="title">usersDataSource</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> DruidDataSourceBuilder.create().build();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>因为我们在 <a href="https://calm_java.gitee.io/blog/2020/01/07/labs-springboot2-datasource-pool/">「5.2 应用配置」</a> 中，将 Druid 自定义的配置项，和数据源的通用配置放在了同一级，所以我们只需使用 <code>@ConfigurationProperties(prefix = &quot;spring.datasource.orders&quot;)</code> 这样的方式即可。</li><li>当然，<a href="https://calm_java.gitee.io/blog/2020/01/07/labs-springboot2-datasource-pool/">「3.3.2 正确的示例」</a> 也是可以这么做的。实际情况下，比较推荐本小节的方式。</li></ul><h2 id="5-4-Application"><a href="#5-4-Application" class="headerlink" title="5.4 Application"></a>5.4 Application</h2><p>创建 <code>Application.java</code> 类，配置 <code>@SpringBootApplication</code> 注解即可。代码如下：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Application.java</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Application</span> <span class="keyword">implements</span> <span class="title">CommandLineRunner</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Logger logger = LoggerFactory.getLogger(Application<span class="class">.<span class="keyword">class</span>)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Resource</span>(name = <span class="string">"ordersDataSource"</span>)</span><br><span class="line">    <span class="keyword">private</span> DataSource ordersDataSource;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Resource</span>(name = <span class="string">"usersDataSource"</span>)</span><br><span class="line">    <span class="keyword">private</span> DataSource usersDataSource;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 启动 Spring Boot 应用</span></span><br><span class="line">        SpringApplication.run(Application<span class="class">.<span class="keyword">class</span>, <span class="title">args</span>)</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">(String... args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// orders 数据源</span></span><br><span class="line">        logger.info(<span class="string">"[run][获得数据源：&#123;&#125;]"</span>, ordersDataSource.getClass());</span><br><span class="line"></span><br><span class="line">        <span class="comment">// users 数据源</span></span><br><span class="line">        logger.info(<span class="string">"[run][获得数据源：&#123;&#125;]"</span>, usersDataSource.getClass());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>执行日志如下：</p><figure class="highlight verilog"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">2020</span>-<span class="number">01</span>-<span class="number">07</span> <span class="number">22</span>:<span class="number">26</span>:<span class="number">11</span><span class="variable">.256</span>  INFO <span class="number">15306</span> --- [           main] c<span class="variable">.j</span><span class="variable">.l</span><span class="variable">.s</span><span class="variable">.d</span><span class="variable">.m</span><span class="variable">.DruidMultipleApplication</span>     : [run][获得数据源：<span class="keyword">class</span> com<span class="variable">.alibaba</span><span class="variable">.druid</span><span class="variable">.spring</span><span class="variable">.boot</span><span class="variable">.autoconfigure</span><span class="variable">.DruidDataSourceWrapper</span>]</span><br><span class="line"><span class="number">2020</span>-<span class="number">01</span>-<span class="number">07</span> <span class="number">22</span>:<span class="number">26</span>:<span class="number">11</span><span class="variable">.257</span>  INFO <span class="number">15306</span> --- [           main] c<span class="variable">.j</span><span class="variable">.l</span><span class="variable">.s</span><span class="variable">.d</span><span class="variable">.m</span><span class="variable">.DruidMultipleApplication</span>     : [run][获得数据源：<span class="keyword">class</span> com<span class="variable">.alibaba</span><span class="variable">.druid</span><span class="variable">.spring</span><span class="variable">.boot</span><span class="variable">.autoconfigure</span><span class="variable">.DruidDataSourceWrapper</span>]</span><br></pre></td></tr></table></figure><ul><li>可以看到，两个 DruidDataSource 成功初始化。</li></ul><h2 id="5-5-监控功能"><a href="#5-5-监控功能" class="headerlink" title="5.5 监控功能"></a>5.5 监控功能</h2><p>和 <a href="https://calm_java.gitee.io/blog/2020/01/07/labs-springboot2-datasource-pool/">「4.4 监控功能」</a> 一致。</p><p>不过呢，我们在监控页面上，可以看到两个 Druid 数据库连接池。</p><h1 id="666-彩蛋"><a href="#666-彩蛋" class="headerlink" title="666. 彩蛋"></a>666. 彩蛋</h1><p>「芋道源码」在知识星球里，做了一波目前在使用的连接池的调查，大概比例是 Druid : HikariCP 为 2:1 左右。猜测随着 Spring Boot 2.X 逐步普及之后，HikariCP 有一定几率反超 Druid 。</p><p>虽然说，HikariCP 没有直接提供监控功能，但是可以使用 <a href="https://prometheus.io/" target="_blank" rel="noopener">Prometheus</a> 采集 Spring Boot Metrics 的数据，后续使用 <a href="https://grafana.com/" target="_blank" rel="noopener">Grafana</a> 制作仪表盘。目前，已经有 <a href="https://grafana.com/grafana/dashboards/6083" target="_blank" rel="noopener">Spring Boot HikariCP / JDBC</a> 可以直接使用。具体怎么做，胖友可以看看 <a href="https://blog.frognew.com/2019/02/spring-boot-guides-hikari.html" target="_blank" rel="noopener">《Spring Boot 中使用 HikariCP 连接池》</a> 文章。</p><p>Druid 的 <a href="https://github.com/alibaba/druid/issues/3047" target="_blank" rel="noopener">Issues 3047</a> 中，也有人提出，是否能够提供 Druid 接入 Prometheus 统一监控的诉求。Druid 目前暂时不支持，不过有聪慧的胖友，提出了使用 <a href="https://github.com/prometheus/jmx_exporter" target="_blank" rel="noopener">Prometheus jmx_exporter</a> 的方式，将 Druid 实现的 JMX 格式的指标暴露出来，提供给 Prometheus 采集监控信息。</p><blockquote><p>旁白君：Sharding-JDBC 是 ShardingSphere 在 JDBC 层面提供的分库分表组件。当然，不仅仅提供分库分表的功能，也提供读写分离、数据脱敏、分布式事务等等功能。</p></blockquote><p>如果胖友工作的比较早，一定还接触过其它连接池。例如说，<a href="https://github.com/swaldman/c3p0" target="_blank" rel="noopener">c3p0</a>、<a href="https://github.com/apache/commons-dbcp" target="_blank" rel="noopener">dbcp</a>、<a href="https://github.com/wwadge/bonecp" target="_blank" rel="noopener">BoneCP</a> 等等。数据库连接池的发展过程，是个非常有意思的历史。感兴趣的胖友，可以看看 <a href="http://www.iocoder.cn/Fight/talk-about-database-connection-pool/?self" target="_blank" rel="noopener">《大话数据库连接池简史，你都用过几个？》</a> 一文，江湖味十足~</p><p>可能胖友会比较纠结，是否要去自定义连接池的配置呢？一般情况下，默认的配置基本能够满足项目的基本要求，不需要特别刻意去修改。当然，这里推荐看两篇文章：</p><ul><li><a href="https://github.com/alibaba/druid/wiki/DruidDataSource配置" target="_blank" rel="noopener">《DruidDataSource 配置》</a> ，Druid 官方提供了通用的配置。</li><li><a href="http://rabbitgyk.com/2018/01/04/druid-configuration/" target="_blank" rel="noopener">《Druid 连接池推荐配置》</a> ，某公司的内部实践</li></ul></div><div class="article-footer"><blockquote class="mt-2x"><ul class="post-copyright list-unstyled"><li class="post-copyright-link hidden-xs"><strong>本文链接：</strong> <a href="https://calm_java.gitee.io/blog/2020/01/07/labs-springboot2-datasource-pool/" title="Spring Boot 数据库连接池入门" target="_blank" rel="external">https://calm_java.gitee.io/blog/2020/01/07/labs-springboot2-datasource-pool/</a></li><li class="post-copyright-license"><strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="http://creativecommons.org/licenses/by/4.0/deed.zh" target="_blank" rel="external">CC BY 4.0 CN协议</a> 许可协议。转载请注明出处！</li></ul></blockquote><div class="panel panel-default panel-badger"><div class="panel-body"><figure class="media"><div class="media-left"><a href="https://github.com/yuyong725" target="_blank" class="img-burn thumb-sm visible-lg"><img src="/blog/images/avatar.jpg" class="img-rounded w-full" alt=""></a></div><div class="media-body"><h3 class="media-heading"><a href="https://github.com/yuyong725" target="_blank"><span class="text-dark">卡姆</span><small class="ml-1x">a Java coder need calm</small></a></h3><div>享受编程</div></div></figure></div></div></div></article><section id="comments"></section></div><nav class="bar bar-footer clearfix" data-stick-bottom><div class="bar-inner"><ul class="pager pull-left"><li class="prev"><a href="/blog/2020/01/08/labs-springboot2-mybatis/" title="Spring Boot MyBatis 入门"><i class="icon icon-angle-left" aria-hidden="true"></i><span>&nbsp;&nbsp;上一篇</span></a></li><li class="next"><a href="/blog/2020/01/07/labs-springboot2-jdbctemplate/" title="Spring Boot JdbcTemplate 入门"><span>下一篇&nbsp;&nbsp;</span><i class="icon icon-angle-right" aria-hidden="true"></i></a></li><li class="toggle-toc"><a class="toggle-btn" data-toggle="collapse" href="#collapseToc" aria-expanded="true" title="文章目录" role="button"><span>[&nbsp;</span><span>文章目录</span> <i class="text-collapsed icon icon-anchor"></i> <i class="text-in icon icon-close"></i> <span>]</span></a></li></ul><button type="button" class="btn btn-fancy btn-donate pop-onhover bg-gradient-warning" data-toggle="modal" data-target="#donateModal"><span>赏</span></button><div class="bar-right"><div class="share-component" data-sites="wechat" data-mobile-sites="wechat"></div></div></div></nav><div class="modal modal-center modal-small modal-xs-full fade" id="donateModal" tabindex="-1" role="dialog"><div class="modal-dialog" role="document"><div class="modal-content donate"><button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button><div class="modal-body"><div class="donate-box"><div class="donate-head"><p>感谢您的支持，我会继续努力的!</p></div><div class="tab-content"><div role="tabpanel" class="tab-pane fade active in" id="alipay"><div class="donate-payimg"><img src="/blog/images/donate/alipayimg.jpeg" alt="扫码支持" title="扫一扫"></div><p class="text-muted mv">扫码打赏，你说多少就多少</p><p class="text-grey">打开支付宝扫一扫，即可进行扫码打赏哦</p></div><div role="tabpanel" class="tab-pane fade" id="wechatpay"><div class="donate-payimg"><img src="/blog/images/donate/wechatpayimg.jpeg" alt="扫码支持" title="扫一扫"></div><p class="text-muted mv">扫码打赏，你说多少就多少</p><p class="text-grey">打开微信扫一扫，即可进行扫码打赏哦</p></div></div><div class="donate-footer"><ul class="nav nav-tabs nav-justified" role="tablist"><li role="presentation" class="active"><a href="#alipay" id="alipay-tab" role="tab" data-toggle="tab" aria-controls="alipay" aria-expanded="true"><i class="icon icon-alipay"></i> 支付宝</a></li><li role="presentation"><a href="#wechatpay" role="tab" id="wechatpay-tab" data-toggle="tab" aria-controls="wechatpay" aria-expanded="false"><i class="icon icon-wepay"></i> 微信支付</a></li></ul></div></div></div></div></div></div></main><footer class="footer" itemscope itemtype="http://schema.org/WPFooter"></footer><script src="//cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script><script>window.jQuery||document.write('<script src="js/jquery.min.js"><\/script>')</script><script src="/blog/js/plugin.min.js"></script><script src="/blog/js/application.js"></script><script>!function(T){var N={TRANSLATION:{POSTS:"文章",PAGES:"页面",CATEGORIES:"分类",TAGS:"标签",UNTITLED:"(未命名)"},ROOT_URL:"/blog/",CONTENT_URL:"/blog/content.json"};T.INSIGHT_CONFIG=N}(window)</script><script src="/blog/js/insight.js"></script><script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><script src="//cdn.jsdelivr.net/npm/gitalk@1.4.0/dist/gitalk.min.js"></script><script src="//cdn.jsdelivr.net/npm/blueimp-md5@2.10.0/js/md5.min.js"></script><script type="text/javascript">var gitalk=new Gitalk({clientID:"adf0c8bfdd8796029917",clientSecret:"a88c2e2e83e2b180f62ad927dcb347871dfe9f4b",repo:"myblog-comment",owner:"yuyong725",admin:["yuyong725"],id:md5(location.pathname),distractionFreeMode:!0});gitalk.render("comments")</script></body></html><!-- rebuild by neat -->